void ScheduleDAGLinearize::Schedule() {
  LLVM_DEBUG(dbgs() << "********** DAG Linearization **********\n");
	
  	//定义一个小型动态数组，用于收集所有“Glue”类型的节点。Glue节点用于表示指令间特殊依赖（如call/flag）。  
  SmallVector<SDNode*, 8> Glues;
    //统计需要调度的节点总数，用于后续分配调度序列空间
  unsigned DAGSize = 0;
    
    //遍历 SelectionDAG 中的所有节点。`DAG->allnodes()` 返回所有 SDNode 的集合。
    //遍历 SelectionDAG 节点时，顺序是自下而上（bottom-up）
  for (SDNode &Node : DAG->allnodes()) {
    SDNode *N = &Node;

    // 用节点的Id来记录每一个节点的度（即被多少节点使用）；N节点的所有输出被其他节点用到的总次数。
    unsigned Degree = N->use_size();
    N->setNodeId(Degree);
    //N节点有多少个输出 value
    unsigned NumVals = N->getNumValues();
      //检查节点是否有 Glue 类型的输出（最后一个值类型为 Glue）并检查 Glue 是否被使用
    if (NumVals && N->getValueType(NumVals-1) == MVT::Glue &&
        N->hasAnyUseOfValue(NumVals-1)) {
        //如果是 Glue 节点，调用 `findGluedUser(N)` 找到 Glue 的最终用户。
      SDNode *User = findGluedUser(N);
        //如果找到用户，则把该 Glue 节点加入 `Glues` 数组，并在 `GluedMap` 里记录 Glue 到用户的映射。
      if (User) {
        Glues.push_back(N);
        GluedMap.insert(std::make_pair(N, User));
      }
    }
	/*
	**作用**：
      - 判断该节点是否需要调度（即会生成 MachineInstr）。
      - `isMachineOpcode()`：节点已经被选择为机器指令。即它已经完成了指令选择阶段
      - `getOpcode() != ISD::EntryToken`：不是入口标记节点。
      - `!isPassiveNode(N)`：不是被认为“被动”的节点（如常量等）。
      	即不会生成实际机器指令的节点，比如常量、EntryToken、调试信息等，这种节点只是数据流或依赖链上的辅助节点，不需要调度，也		不会变成汇编指令。
      - 满足条件则统计到 `DAGSize`，用于后续分配调度序列空间。
	*/
    if (N->isMachineOpcode() ||
        (N->getOpcode() != ISD::EntryToken && !isPassiveNode(N)))
      ++DAGSize;
  }
    
	//遍历所有 Glue 节点，获取其用户节点和各自的“度”。
  for (SDNode *Glue : Glues) {
    SDNode *GUser = GluedMap[Glue];
    unsigned Degree = Glue->getNodeId();
    unsigned UDegree = GUser->getNodeId();

    /*
    - **作用**：
      - Glue 用户必须和 Glue 节点一起调度，Glue 的其他用户也算 Glue 用户的用户。
      - `getGluedUser()` 获取 Glue 节点的直接用户。即第一个使用这个Glue值的节点
      - 遍历 Glue 节点的所有用户，如果是直接用户，则减少 Glue 的“度”。
      - Glue 用户的“度”增加 Glue 节点的“度”，Glue 节点的“度”设为 1，确保调度顺序正确。
    */
    SDNode *ImmGUser = Glue->getGluedUser();
      //Glue节点作为输入，被哪些节点用到了，这些节点就是Glue的“uses”。
    for (const SDNode *U : Glue->uses())
        //遍历 Glue 的所有用户（uses()），如果某个用户就是直接用户，则把 Glue 的“度”减一（因为这个依赖会被 Glue 用户一起带走，不需要单独计数）。
      if (U == ImmGUser)
        --Degree;
      //Glue用户的“度”增加Glue节点的“度”，是为了把Glue的所有依赖都归到Glue用户身上，保证Glue和Glue用户一起调度，不会被其他节点插队。
    GUser->setNodeId(UDegree + Degree);
      //把 Glue 节点的“度”设为 1，意思是：Glue 只需要等它的用户就可以被调度，不会被提前调度。
    Glue->setNodeId(1);
  }
	//为调度序列预分配空间，提升效率。`Sequence` 是最终调度顺序的容器。
  Sequence.reserve(DAGSize);
    //从 DAG 的根节点开始递归调度。`ScheduleNode` 会递归处理所有依赖节点，保证所有依赖先于当前节点被调度，并将节点加入 `Sequence`。
  ScheduleNode(DAG->getRoot().getNode());
}